package server

import (
	"encoding/hex"
	"fmt"
	"github.com/pion/sdp/v3"
)

type StreamPlayer struct {
	id      int32
	session *RtspSession

	path  string
	query string

	tracks Tracks
	Tracks []*PlayerTrack

	pusher *StreamPusher
}

func NewStreamPlayer(session *RtspSession, pusher *StreamPusher, query string) (*StreamPlayer, error) {
	if len(pusher.Tracks) == 0 {
		return nil, fmt.Errorf("no stream tracks")
	}

	c := &StreamPlayer{
		id:      GetId(),
		session: session,
		pusher:  pusher,
		path:    pusher.GetPath(),
		query:   query,
	}

	{
		var tracks = make(Tracks, 0, len(pusher.Tracks))
		for _, streamTrack := range pusher.Tracks {
			tracks = append(tracks, streamTrack.track)
		}

		var err error
		c.tracks, err = ReadTracks(tracks.Write(false))
		if err != nil {
			return nil, err
		}
	}

	for _, track := range c.tracks {
		if track.Media.MediaName.Media != MediaTypeVideo && track.Media.MediaName.Media != MediaTypeAudio {
			return nil, fmt.Errorf("error media type")
		}

		// control streamid=0
		control, ok := track.Media.Attribute("control")
		if !ok {
			return nil, fmt.Errorf("no control attribute")
		}

		playTrack, err := NewPlayTrack(control, c, track)
		if err != nil {
			return nil, fmt.Errorf("new track fail %v", err)
		}

		cname := fmt.Sprintf("%v_%v", hex.EncodeToString([]byte(c.path)), playTrack.GetSSRC())
		track.Media.WithValueAttribute(sdp.AttrKeySSRC, fmt.Sprintf("%d cname:%s", playTrack.GetSSRC(), cname))

		c.Tracks = append(c.Tracks, playTrack)
	}

	return c, nil
}

// GetTrackFromControl streamid=[0/1]
func (c *StreamPlayer) GetTrackFromControl(trackControl string) (*PlayerTrack, bool) {
	for _, track := range c.Tracks {
		if track.control == trackControl {
			return track, true
		}
	}

	return nil, false
}

func (c *StreamPlayer) GetPath() string {
	if c.pusher == nil {
		return ""
	}

	return c.pusher.GetPath()
}

func (c *StreamPlayer) Play() {
	// 添加所有track, 拉取所有流
	for _, playTracker := range c.Tracks {
		if pushTracker, ok := c.pusher.GetTrackFromControl(playTracker.control); ok {
			playTracker.rtpBufferIndex = pushTracker.AddRtpBuffer(playTracker.rtpBuffer)
		}
	}
}

func (c *StreamPlayer) Pause() {
	// 移除所有track
	for _, playTracker := range c.Tracks {
		if pushTracker, ok := c.pusher.GetTrackFromControl(playTracker.control); ok {
			pushTracker.RemoveRtpBuffer(playTracker.rtpBufferIndex)
		}
	}
}

func (c *StreamPlayer) Stop() {
	c.Pause()
}

func (c *StreamPlayer) Close() {
	c.Stop()

	// 关闭track
	for _, playTracker := range c.Tracks {
		playTracker.Close()
	}
}
